﻿#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif

#include "win.h"
#include "ui_win.h"
#include <QDebug>
#include <QRegExp>
#include <QRegExpValidator>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>
#include <QFile>

using namespace std;

win::win(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::win)
{
    ui->setupUi(this);
    connect(this->ui->anniu,SIGNAL(clicked()),this,SLOT(cao()));    //按钮的槽函数
    connect(ui->lineEdit,&QLineEdit::returnPressed,this,&win::cao); //回车槽函数连接
    //connect(ui->lineEdit,SIGNAL(returnPressed()),this,SLOT(cao()));——QT5之前的旧写法

    naManager = new QNetworkAccessManager(this);    //网络模块
    connect(naManager,SIGNAL(finished(QNetworkReply*)),this,SLOT(requestFinished(QNetworkReply*))); //连接请求完成后触发的槽函数
    connect(naManager,SIGNAL(finished(QNetworkReply*)),&loop,SLOT(quit()));
    connect(ui->bianmaxuanze,SIGNAL(clicked()),this,SLOT(bianmaqiehuan()));

    ui->jindutiao->reset();
    renwulanbut = new QWinTaskbarButton(this);
    renwulanjindutiao = renwulanbut->progress();
    renwulanjindutiao->show();
    renwulanjindutiao->setRange(0,10000);
    renwulanjindutiao->reset();

//    ui->wenben->appendPlainText("### 建议安装：“Microsoft Visual C++ 2015-2019 Redistributable X86”运行库。");
    ui->wenben->appendPlainText("### 文件位置：下载完成后，字幕文件位于程序相同目录下。\n");
    ui->wenben->appendPlainText("### 查看BV号：URL www.bilibili.com/video/BV1w4411P7xn?from=search 中，BV号为BV二字到问号前，即1w4411P7xn或BV1w4411P7xn（都可用）。");
}
win::~win(){delete ui;}

void win::cao(){    //按钮的槽函数
    QString avhao = ui->lineEdit->text();
    if (avhao.size()==0){
        ui->wenben->appendPlainText("#错误：请输入BV号。");return;
    }
    ui->wenben->appendPlainText("#下载：目标BV号"+avhao);
    getShiPinLeiBiao(avhao);
    if (muLuArray.size()==0){
        return;
    }
    renwulanbut->setWindow(windowHandle());
    ui->jindutiao->setRange(0,10000);
    jin = 10000/muLuArray.size();
    for (int j=0;j<muLuArray.size();j++) {
        ui->jindutiao->setValue(j*jin);
        renwulanjindutiao->setValue(j*jin);
        QJsonObject danTiaoMuLu = muLuArray.at(j).toObject();
        pming = danTiaoMuLu.value("part").toString();
        QString cid = QString::number(danTiaoMuLu.value("cid").toInt());
        xiaZaiDanPZiMu(avhao,cid,j+1);
    }
    ui->jindutiao->setValue(10000);
    ui->jindutiao->setFormat(QString("完成"));
    renwulanjindutiao->reset();
    ui->wenben->appendPlainText("#任务完成。\n");return;
}

void win::xiaZaiDanPZiMu(QString bvid,QString cid,int p){    //根据aid和cid下载某P视频内的字幕，变量p用于命名。
//    QString url = "https://api.bilibili.com/x/web-interface/view?bvid="+bvid+"&cid="+cid;
    QString url = "https://api.bilibili.com/x/player/v2?bvid="+bvid+"&cid="+cid;
    ui->wenben->appendPlainText("#请求："+url);
    naManager->get(QNetworkRequest (QUrl(url)));//Get Url，获取json字幕
    loop.exec();                                //进入事件循环，等待get请求完成。

    biaoti = bvid;
    QJsonArray jsonUrlArray = QJsonDocument::fromJson(linShi).object().value("data").toObject().value("subtitle").toObject().value("subtitles").toArray();
    qDebug()<<jsonUrlArray;
    if(jsonUrlArray.size()<1){
        ming = QString("%1 - P%2：%3").arg(biaoti).arg(p).arg(pming);
        ui->wenben->appendPlainText("#无字幕："+ming);
        return;
    }
    else{
        QJsonObject danurl;
        int jinn = jin/jsonUrlArray.size();
        for (int i=0;i<jsonUrlArray.size();i++) {
            danurl = jsonUrlArray.at(i).toObject();
            qDebug()<<danurl.value("subtitle_url");
            ming = QString("%1 - P%2：%3 - %4").arg(biaoti).arg(p).arg(pming).arg(danurl.value("lan").toString());
            getJsonZhuanSrt(danurl.value("subtitle_url").toString());
            ui->wenben->appendPlainText("#输出："+ming);
            ui->jindutiao->setValue(jinn+ui->jindutiao->value());
            renwulanjindutiao->setValue(jinn+ui->jindutiao->value());
        }
    }
    ui->wenben->moveCursor(QTextCursor::End);
};

QJsonArray win::getShiPinLeiBiao(QString avhao){    //Get视频列列表
    QString avurl = "https://api.bilibili.com/x/player/pagelist?bvid=" + avhao;  //创建URL
    naManager->get(QNetworkRequest (QUrl(avurl)));  //提交Get请求
    loop.exec();    //进入事件循环，等待get请求完成。
    qDebug()<<linShi;
    if(linShi==""){
        ui->wenben->appendHtml("#请求失败，建议检查网络或重试。");
        QJsonArray m;
        return m;
    }
    QJsonDocument muLuDoc = QJsonDocument::fromJson(linShi);
    QJsonObject muLuObj = muLuDoc.object();
    if(muLuObj.value("message").toString()=="请求错误"){
        ui->wenben->appendPlainText("#网络请求成功，服务器返回错误，请检查BV号。");
        QJsonArray m;
        return m;
    }
    if(muLuObj.value("message").toString()=="0"){ui->wenben->appendPlainText("#网络请求成功，服务器正常返回视频列表。");}

    muLuArray = muLuObj.value("data").toArray();
    return muLuArray;
}

void win::getJsonZhuanSrt(QString url){    //获取Json格式的CC字幕，转换输出标准Srt字幕
    naManager->get(QNetworkRequest (QUrl("Http:"+url)));//Get Url，获取json字幕
    loop.exec();                                //进入事件循环，等待get请求完成。
    QByteArray ziMuJson = linShi;               //获取返回内容

    QFile ziMuSrt(qv(ming) + ".srt");           //创建Srt字幕文件
    ziMuSrt.open(QIODevice::WriteOnly|QIODevice::Text);

//    QJsonDocument jsonDoc = QJsonDocument::fromJson(ziMuJson);  //QbyteArray转QJsonObject
    QJsonObject jsonObj = QJsonDocument::fromJson(ziMuJson).object();
    QJsonArray jsonBody = jsonObj.value("body").toArray();      //取"body"部分转QJsonArray

    //遍历Array，转Object读取内容，转换格式
    QString zimu;
    for (int i=0;i<jsonBody.size();i++) {
        QJsonObject danTiaoZiMuJsonObj = jsonBody.at(i).toObject();
        QString f =miaoShuZhuanHuan(danTiaoZiMuJsonObj.value("from").toDouble());
        QString t =miaoShuZhuanHuan(danTiaoZiMuJsonObj.value("to").toDouble());
        QString c =danTiaoZiMuJsonObj.value("content").toString();
        zimu += QString::number(i+1)+"\n"+f+" --> "+t+"\n"+c+"\n\n";
    }
    ziMuSrt.write(zhuanbianma(zimu));
    ziMuSrt.close();    //关闭文件
}

void win::bianmaqiehuan(){  //切换编码
    if(bianma=="UTF-8"){bianma = "GB2312";}
    else{bianma = "UTF-8";}
    ui->wenben->appendPlainText("【消息】输出编码变更："+bianma);
}

QByteArray win::zhuanbianma(QString str){   //转换编码
    if (bianma=="GB2312"){return str.toLocal8Bit();}
    return str.toUtf8();

}

QString win::miaoShuZhuanHuan(double miaoShu){     //输入秒数，转换为(时:分:秒,毫秒)格式
    QStringList list = QString::number(miaoShu).split(".");
    int i = list.at(0).toInt();

    QString shi,fen,miao,haomiao;
    shi = QString::number(i/3600);
    fen = QString::number(i/60%60);
    miao = QString::number(i%60);
    if (shi.size()<2){shi = "0"+shi;}
    if (fen.size()<2){fen = "0"+fen;}
    if (miao.size()<2){miao = "0"+miao;}

    if (list.size()==1){
        haomiao = "000";
    }
    else{
        haomiao = list.at(1);
        if (haomiao.size()>3){
            haomiao = haomiao.mid(0,3);
        }
        else if (haomiao.size()==1){haomiao = haomiao+"00";}
        else if (haomiao.size()==2){haomiao = haomiao+"0";}
    }

    return QString(shi+":"+fen+":"+miao+","+haomiao);
}

QString win::qv(QString str){   //去除特殊符号
    str.replace("/","、");
    str.replace("\\","、");
    str.replace("|","｜");
    str.replace("*","X");
    str.replace(":","：");
    str.replace("?","？");
    str.replace("<","《");
    str.replace(">","》");
    str.replace("\"","“");
    str.replace("\"","”");
    qDebug()<<str;
    return str;
}

void win::requestFinished(QNetworkReply *reply) {   //请求完成后触发的槽函数
    linShi = reply->readAll();  //返回内容写入到临时储存用的变量
    loop.exit();    //请求结束，关闭事件循环
}
